﻿using LightCAD.Core.Elements;
using LightCAD.Three;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Drawing.Actions.Action
{
    public class DrawingOrderAction : ITransformDrawer
    {
        public static string CommandName;
        protected DocumentRuntime docRt;
        protected ViewportRuntime vportRt;
        protected IDocumentEditor docEditor;
        protected ICommandControl commandCtrl;
        private string CurrentTransform;
        private ElementSetInputer ElementInputers { get; set; }

        private DrawingOrderAction() { }

        private static readonly LcCreateMethod[] CreateMethods;

        static DrawingOrderAction()
        {
            CommandName = "DRAWINGORDER";
            CreateMethods = new LcCreateMethod[4];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "PRE",
                Description = "前置",
                Steps = new LcCreateStep[]
               {
                    new LcCreateStep { Name=  "Step0", Options= "PRE 选择对象:" },
               }
            };

            CreateMethods[1] = new LcCreateMethod()
            {
                Name = "POST",
                Description = "后置",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name=  "Step0", Options= "POST 选择对象:" },
                }
            };

            CreateMethods[2] = new LcCreateMethod()
            {
                Name = "UP",
                Description = "置于对象之上",
                Steps = new LcCreateStep[]
                    {
                    new LcCreateStep { Name = "Step0", Options = "选择对象：" },
                    new LcCreateStep { Name = "Step1", Options = "选择参照对象：" },
                    }
            };
            CreateMethods[3] = new LcCreateMethod()
            {
                Name = "DOWN",
                Description = "置于对象之下",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name = "Step0", Options = "选择对象：" },
                    new LcCreateStep { Name = "Step1", Options = "选择参照对象：" },
                }
            };
        }

        public DrawingOrderAction(IDocumentEditor docEditor)
        {
            this.docEditor = docEditor;
            this.docRt = docEditor.DocRt;
            this.vportRt = (docEditor as DrawingEditRuntime).ActiveViewportRt;
            this.commandCtrl = this.vportRt.CommandCtrl;
            this.commandCtrl.WriteInfo("命令" + CommandName);
        }
        List<LcElement> selectedElements01 = new List<LcElement>();
        List<LcElement> selectedElements02 = new List<LcElement>();
        List<LcElement> selectedElements11 = new List<LcElement>();
        List<LcElement> selectedElements12 = new List<LcElement>();
        ElementCollection allElements = new ElementCollection();

        //单独调用方法
        public async void ExecCreate(string[] args)
        {
            string str = null;
            foreach (var item in args)
            {
                str += item;
            }
            switch (str)
            {
                case "PRE":
                    Prepose();
                    break;
                case "POST":
                    Postpose();
                    break;
                case "UP":
                    ChangeSeatUP();
                    break;
                case "DOWN":
                    ChangeSeatDOWN();
                    break;
                default:
                    Prepose();
                    break;
            }
        }

        // 前置
        public async void Prepose()
        {
            this.StartAction();
            var curMethod = CreateMethods[0];
            this.ElementInputers = new ElementSetInputer(this.docEditor);
            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.selectedElements11.AddRange(this.docRt.Action.SelectedElements);
                goto Step1;
            }
            else
            {
                goto Step0;
            }

        Step0:
            var step01 = curMethod.Steps[0];
            var result01 = await ElementInputers.Execute(step01.Options);
            this.selectedElements01.AddRange(this.docRt.Action.SelectedElements);


            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result01 == null)
            {
                this.Cancel();
                return;
            }
            if (result01.ValueX == null)
            {
                goto Step0;
            }

            int indexS01 = 0;

            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag0 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements01[0])
                {
                    indexS01 = i;
                    flag0 = true;
                }
            }
            if (flag0)
            {
                allElements.Remove(allElements[indexS01]);
                allElements.Insert(allElements.Count, selectedElements01[0]);
                goto End;
            }
        Step1:
            var step11 = curMethod.Steps[0];
            ElementInputers.Execute(step11.Options);
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            int indexS11 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag11 = false;

            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements11[0])
                {
                    indexS11 = i;
                    flag11 = true;
                }
            }
            if (flag11)
            {
                allElements.Remove(allElements[indexS11]);
                allElements.Insert(allElements.Count, selectedElements11[0]);
                goto End;
            }
        End:
            this.EndAction();
        }
        //后置
        public async void Postpose()
        {
            this.StartAction();
            this.CurrentTransform = "POSTPOSE";
            var curMethod = CreateMethods[1];

            this.ElementInputers = new ElementSetInputer(this.docEditor);

            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.selectedElements11.AddRange(this.docRt.Action.SelectedElements);
                goto Step1;
            }
            else
            {
                goto Step0;
            }

        Step0:
            var step01 = curMethod.Steps[0];
            var result01 = await ElementInputers.Execute(step01.Options);
            this.selectedElements01.AddRange(this.docRt.Action.SelectedElements);


            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result01 == null)
            {
                this.Cancel();
                return;
            }
            if (result01.ValueX == null)
            {
                goto Step0;
            }

            int indexS01 = 0;

            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag0 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements01[0])
                {
                    indexS01 = i;
                    flag0 = true;
                }
            }
            if (flag0)
            {
                allElements.Remove(allElements[indexS01]);
                allElements.Insert(0, selectedElements01[0]);
                goto End;
            }
        Step1:
            var step11 = curMethod.Steps[0];
            ElementInputers.Execute(step11.Options);
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            int indexS11 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag11 = false;

            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements11[0])
                {
                    indexS11 = i;
                    flag11 = true;
                }
            }
            if (flag11)
            {
                allElements.Remove(allElements[indexS11]);
                allElements.Insert(0, selectedElements11[0]);
                goto End;
            }
        End:
            this.EndAction();
        }
        //置于对象之上
        public async void ChangeSeatUP()
        {
            this.StartAction();
            this.CurrentTransform = "CSUP";
            var curMethod = CreateMethods[2];
            this.ElementInputers = new ElementSetInputer(this.docEditor);

            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.selectedElements11.AddRange(this.docRt.Action.SelectedElements);
                goto Step1;
            }
            else
            {
                goto Step0;
            }

        Step0:
            var step01 = curMethod.Steps[0];
            var result01 = await ElementInputers.Execute(step01.Options);
            this.selectedElements01.AddRange(this.docRt.Action.SelectedElements);
            var step02 = curMethod.Steps[1];
            var result02 = await ElementInputers.Execute(step02.Options);
            foreach (var item in result02.ValueX as List<LcElement>)
            {
                if (!selectedElements01.Contains(item))
                {
                    selectedElements02.Add(item);
                }
            }
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result01 == null || result02 == null)
            {
                this.Cancel();
                return;
            }
            if (result01.ValueX == null)
            {
                goto Step0;
            }
            if (result01.ValueX != null)
            {
                if (result02.ValueX == null)
                {
                    goto Step1;
                }
            }
            int indexS01 = 0;
            int indexS02 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag01 = false;
            bool flag02 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements01[0])
                {
                    indexS01 = i;
                    flag01 = true;
                }
                if (allElements[i] == selectedElements02[0])
                {
                    indexS02 = i;
                    flag02 = true;
                }
            }
            if (flag01 && flag02)
            {
                if (indexS01 > indexS02)
                {
                    goto End;
                }
                allElements.Remove(allElements[indexS01]);
                allElements.Insert(indexS02, selectedElements01[0]);
                goto End;
            }
        Step1:
            var step11 = curMethod.Steps[1];
            var result11 = await ElementInputers.Execute(step11.Options);
            foreach (var item in result11.ValueX as List<LcElement>)
            {
                if (!selectedElements11.Contains(item))
                {
                    selectedElements12.Add(item);
                }
            }
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result11 == null)
            {
                this.Cancel();
                return;
            }
            if (result11.ValueX == null)
            {
                goto Step1;
            }
            int indexS11 = 0;
            int indexS12 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag11 = false;
            bool flag12 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements11[0])
                {
                    indexS11 = i;
                    flag11 = true;
                }
                if (allElements[i] == selectedElements12[0])
                {
                    indexS12 = i;
                    flag12 = true;
                }
            }
            if (flag11 && flag12)
            {
                if (indexS11 > indexS12)
                {
                    goto End;
                }
                allElements.Remove(allElements[indexS11]);
                allElements.Insert(indexS12, selectedElements11[0]);
                goto End;
            }
        End:
            this.EndAction();
        }
        //置于对象之下
        public async void ChangeSeatDOWN()
        {
            this.StartAction();
            this.CurrentTransform = "CSDOWN";
            var curMethod = CreateMethods[3];
            this.ElementInputers = new ElementSetInputer(this.docEditor);

            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.selectedElements11.AddRange(this.docRt.Action.SelectedElements);
                goto Step1;
            }
            else
            {
                goto Step0;
            }

        Step0:
            var step01 = curMethod.Steps[0];
            var result01 = await ElementInputers.Execute(step01.Options);
            this.selectedElements01.AddRange(this.docRt.Action.SelectedElements);
            var step02 = curMethod.Steps[1];
            var result02 = await ElementInputers.Execute(step02.Options);
            foreach (var item in result02.ValueX as List<LcElement>)
            {
                if (!selectedElements01.Contains(item))
                {
                    selectedElements02.Add(item);
                }
            }
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result01 == null || result02 == null)
            {
                this.Cancel();
                return;
            }
            if (result01.ValueX == null)
            {
                goto Step0;
            }
            if (result01.ValueX != null)
            {
                if (result02.ValueX == null)
                {
                    goto Step1;
                }
            }
            int indexS01 = 0;
            int indexS02 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag01 = false;
            bool flag02 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements01[0])
                {
                    indexS01 = i;
                    flag01 = true;
                }
                if (allElements[i] == selectedElements02[0])
                {
                    indexS02 = i;
                    flag02 = true;
                }
            }
            if (flag01 && flag02)
            {
                if (indexS01 < indexS02)
                {
                    goto End;
                }
                allElements.Remove(allElements[indexS01]);
                allElements.Insert(indexS02, selectedElements01[0]);
                goto End;
            }
        Step1:
            var step11 = curMethod.Steps[1];
            var result11 = await ElementInputers.Execute(step11.Options);
            foreach (var item in result11.ValueX as List<LcElement>)
            {
                if (!selectedElements11.Contains(item))
                {
                    selectedElements12.Add(item);
                }
            }
            if (ElementInputers.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result11 == null)
            {
                this.Cancel();
                return;
            }
            if (result11.ValueX == null)
            {
                goto Step1;
            }
            int indexS11 = 0;
            int indexS12 = 0;
            this.allElements = this.docEditor.DocRt.Document.ModelSpace.Elements;
            bool flag11 = false;
            bool flag12 = false;
            for (int i = 0; i < allElements.Count; i++)
            {
                if (allElements[i] == selectedElements11[0])
                {
                    indexS11 = i;
                    flag11 = true;
                }
                if (allElements[i] == selectedElements12[0])
                {
                    indexS12 = i;
                    flag12 = true;
                }
            }
            if (flag11 && flag12)
            {
                if (indexS11 < indexS12)
                {
                    goto End;
                }
                allElements.Remove(allElements[indexS11]);
                allElements.Insert(indexS12, selectedElements11[0]);
                goto End;
            }
        End:
            this.EndAction();
        }
        //渲染
        public virtual void DrawTrans(SKCanvas canvas)   
        {

        }

        public void StartAction()
        {
            if (vportRt.CheckStatus(ViewportStatus.InAction))
            {
                vportRt.CancelCurrentAction();
            }
            vportRt.SetStatus(ViewportStatus.InAction);
            this.vportRt.CommandCenter.InAction = true;
        }

        protected void DetachEvents()
        {

        }

        public void Cancel()
        {
            this.DetachEvents();
            this.EndAction();
        }

        public void EndAction()
        {
            this.vportRt.SetTransformDrawer(null);
            vportRt.ClearStatus();
            this.commandCtrl.Prompt(string.Empty);

            this.vportRt.CurrentAction = null;
            this.vportRt.CursorType = LcCursorType.SelectElement;
            this.vportRt.CursorAddon = CursorAddonType.None;
            this.vportRt.CommandCenter.InAction = false;
            this.vportRt.CancelCurrentAction();
            if (this.docRt.Action.SelectedElements.Count > 0)
            {
                this.docRt.Action.SetSelectsToDragging(false);
                this.vportRt.ClearElementGrips();
                this.docRt.Action.ClearSelects();
            }
        }

    }
}
